/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.modules.mes.base.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.mp.base.BaseEntity;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.CollectionUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.mes.base.entity.PrdBom;
import org.springblade.modules.mes.base.entity.PrdInfo;
import org.springblade.modules.mes.base.service.IPrdBomService;
import org.springblade.modules.mes.base.service.IPrdInfoService;
import org.springblade.modules.mes.base.utils.StringUtils;
import org.springblade.modules.mes.base.vo.PrdInfoVO;
import org.springblade.modules.mes.base.wrapper.PrdInfoWrapper;
import org.springblade.modules.mes.opcua.constant.OpcUaCache;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 产品信息 控制器
 *
 * @author BladeX
 * @since 2020-09-08
 */
@RestController
@AllArgsConstructor
@RequestMapping("/prdinfo")
@Api(value = "产品信息", tags = "产品信息接口")
public class PrdInfoController extends BladeController {

	private final IPrdInfoService prdInfoService;

	private final IPrdBomService prdBomService;

	/**
	 * 详情
	 */
	@GetMapping("/detail")
	//@ApiOperationSupport(order = 1)
	@ApiOperation(value = "详情", notes = "传入prdInfo")
	public R<PrdInfoVO> detail(PrdInfoVO prdInfoVO) {
		PrdInfo detail = prdInfoService.getOne(Condition.getQueryWrapper(prdInfoVO));
		PrdInfoVO result = PrdInfoWrapper.build().entityVO(detail);


		return R.data(result);
	}


	/**
	 * 不分页 产品列表
	 */
	@GetMapping("/list")
	@ApiOperation(value = "不分页", notes = "传入prdType")
	public R<List<PrdInfoVO>> list(PrdInfoVO prdInfoVO) {
		List<PrdInfoVO> prdInfoVOList = prdInfoService.getPrdInfoVOList(prdInfoVO);
		return R.data(prdInfoVOList);
	}

	/**
	 * 销售用-FIS在用
	 *
	 * @param produceCode
	 * @return
	 */
	@GetMapping("/getMdMaterial")
	@ApiOperation(value = "通过编码获取信息", notes = "传入produceCode")
	public R<PrdInfoVO> getMdMaterial(String produceCode) {
		if (StringUtils.isEmpty(produceCode)) {
			return R.fail("参数不能为空！");
		}
		PrdInfo prdInfo = prdInfoService.getOne(new LambdaQueryWrapper<PrdInfo>().eq(PrdInfo::getMaterialNo, produceCode));
		PrdInfoVO prdInfoVO = BeanUtil.copy(prdInfo, PrdInfoVO.class);
		return R.data(prdInfoVO);
	}

	/**
	 * 不分页 产品列表
	 * 根据名称模糊搜索，如果没传返回空
	 */
	@GetMapping("/listByName")
	@ApiOperation(value = "不分页", notes = "传入prdName")
	public R<List<PrdInfoVO>> listByName(String prdName, String productType) {
		List<PrdInfoVO> prdInfoVOList = prdInfoService.listByName(prdName, productType);
		return R.data(prdInfoVOList);
	}


	/**
	 * 质量用
	 */
	@GetMapping("/listByNameQua")
	@ApiOperation(value = "质量用", notes = "传入prdName")
	public R<List<PrdInfoVO>> listByNameQua(String prdName, String productType) {
		List<PrdInfoVO> prdInfoVOList = prdInfoService.listByNameQua(prdName, productType);
		return R.data(prdInfoVOList);
	}


	/**
	 * 自定义分页 产品信息
	 */
	@GetMapping("/page")
	@ApiOperation(value = "分页", notes = "传入prdInfo")
	public R<IPage<PrdInfoVO>> page(PrdInfoVO prdInfo, Query query) {
		IPage<PrdInfoVO> pages = prdInfoService.selectPrdInfoPage(Condition.getPage(query), prdInfo);
		return R.data(pages);
	}

	/**
	 * 自定义分页 顶级产品且类型为供货级的产品列表
	 */
	@GetMapping("/topprdpage")
	@ApiOperation(value = "分页", notes = "传入prdInfo")
	public R<IPage<PrdInfoVO>> topPrdPage(PrdInfoVO prdInfo, Query query) {
		IPage<PrdInfoVO> pages = prdInfoService.selectTopPrdInfoPage(Condition.getPage(query), prdInfo);
		return R.data(pages);
	}

	/**
	 * 新增 产品信息
	 */
	@PostMapping("/save")
	@ApiOperation(value = "新增", notes = "传入prdInfo")
	public R save(@Valid @RequestBody PrdInfoVO prdInfoVO) {
		try {
			long count = prdInfoService.count(new LambdaQueryWrapper<PrdInfo>().eq(PrdInfo::getMaterialNo, prdInfoVO.getMaterialNo()));
			if (count > 0) {
				return R.fail("产品编码已存在，请重新填写！");
			}
			StringBuilder s = new StringBuilder();
			s.append(prdInfoVO.getProductionLineCode()).append("-").append(prdInfoVO.getMaterialType()).append("-").append(prdInfoVO.getMaterialSubType());
			prdInfoVO.setMaterialGroupNo(s.toString());
			return R.status(prdInfoService.save(prdInfoVO));
		} finally {
			OpcUaCache.clear();
		}
	}

	/**
	 * 根据编码修改产品价格
	 */
	@PostMapping("/updateProductUnitPrice")
	@ApiOperation(value = "根据编码修改产品价格", notes = "传入prdInfo")
	public R updateProductUnitPrice(@Valid @RequestBody PrdInfoVO prdInfoVO) {
		try {
			return prdInfoService.updateProductUnitPrice(prdInfoVO);
		} finally {
			OpcUaCache.clear();
		}
	}

	/**
	 * 修改 产品信息
	 */
	@PostMapping("/update")
	@ApiOperation(value = "修改", notes = "传入prdInfo")
	public R update(@Valid @RequestBody PrdInfoVO prdInfoVO) {
		try {
			long count = prdInfoService.count(new LambdaQueryWrapper<PrdInfo>().ne(BaseEntity::getId, prdInfoVO.getId()).eq(PrdInfo::getMaterialNo, prdInfoVO.getMaterialNo()));
			if (count > 0) {
				return R.fail("产品编码已存在，请重新填写！");
			}
			if (prdInfoVO.getProductionLineCode() != null && prdInfoVO.getMaterialType() != null) {
				StringBuilder s = new StringBuilder();
				s.append(prdInfoVO.getProductionLineCode()).append("-").append(prdInfoVO.getMaterialType()).append("-").append(prdInfoVO.getMaterialSubType());
				prdInfoVO.setMaterialGroupNo(s.toString());
			}
			boolean flag = prdInfoService.updateById(prdInfoVO);
			return R.status(flag);
		} finally {
			OpcUaCache.clear();
		}
	}


	/**
	 * 删除 产品信息
	 */
	@PostMapping("/remove")
	//@ApiOperationSupport(order = 7)
	@ApiOperation(value = "逻辑删除", notes = "传入ids")
	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids, String productDrawingNos) {
		try {
			//状态为"生产中"状态的产品不能删除(1-新建，2-生产中，3-停产)
			List<PrdInfo> prdInfoList = prdInfoService.list(new QueryWrapper<PrdInfo>().in("id", Func.toLongList(ids)));

			List<String> productNoList = prdInfoList.stream().map(PrdInfo::getMaterialNo).collect(Collectors.toList());
			List<PrdBom> bomList = prdBomService.list(new QueryWrapper<PrdBom>().lambda().in(PrdBom::getMaterialNo, productNoList).or().in(PrdBom::getDirectLeaderNo, productNoList));
			for (PrdInfo prdInfo : prdInfoList) {
				List<PrdBom> curBomList = bomList.stream()
					.filter(x -> x.getMaterialNo().equals(prdInfo.getMaterialNo()) || x.getDirectLeaderNo().equals(prdInfo.getMaterialNo()))
					.collect(Collectors.toList());
				if (CollectionUtil.isNotEmpty(curBomList)) {
					List<String> bomNoList = curBomList.stream().map(PrdBom::getDirectLeaderNo).distinct().collect(Collectors.toList());
					String join = String.join(",", bomNoList);
					String msg = String.format("产品编码:%s,在Bom中被引用,无法删除.Bom:%s", prdInfo.getMaterialNo(), join);
					return R.fail(msg);
				}
			}

			for (PrdInfo item : prdInfoList) {
				if ("2".equals(item.getProductStatus())) {
					return R.fail("产品编码：" + item.getMaterialNo() + "，产品状态为【生产中】，无法删除！");
				}
			}

			boolean flag = prdInfoService.deletePrdAndBom(Func.toLongList(ids), null);


			return R.status(flag);

		} finally {
			OpcUaCache.clear();
		}
	}


	/**
	 * 新增BOM,产品下拉选
	 * 只能选BOM标识为BOM的
	 */
	@GetMapping("/bomPrdSelected")
	@ApiOperation(value = "新增BOM,产品下拉选", notes = "")
	public R<List<PrdInfo>> bomPrdSelected(String flag) {
		if (StringUtils.isEmpty(flag)) {//配方
			List<PrdInfo> list = prdInfoService.list(new QueryWrapper<PrdInfo>().eq("quota_flag", "2").eq("material_flag", "P")
				.last("and not exists (select material_no from prj_prd_bom " +
					"where material_no=md_material.material_no and (direct_leader_no is null or direct_leader_no ='')) order by create_time desc"));//查询是否bom为是(2)并且未创建过bom的产成品数据
			return R.data(list);
		} else {//bom
			List<PrdInfo> list = prdInfoService.list(new QueryWrapper<PrdInfo>().eq("quota_flag", "2").eq("material_flag", "P")
				.last("and not exists (select material_no from prj_prd_bom_sap " +
					"where material_no=md_material.material_no and (direct_leader_no is null or direct_leader_no ='')) order by create_time desc"));//查询是否bom为是(2)并且未创建过bom的产成品数据
			return R.data(list);
		}
	}

	/**
	 * 新增BOM,产品下拉选
	 * 只能选BOM标识为BOM的
	 */
	@GetMapping("/bomPrdSelected2")
	public R<List<PrdInfo>> bomPrdSelected2() {
		List<PrdInfo> list = prdInfoService.list(new QueryWrapper<PrdInfo>().eq("material_flag", "P"));
		return R.data(list);
	}


	/**
	 * 根据物料类型和物料组查询所有物料
	 */
	@GetMapping("/materialByTypeAndGroup")
	//@ApiOperationSupport(order = 2)
	@ApiOperation(value = "根据物料类型和物料组查询所有物料", notes = "")
	public R<List<PrdInfoVO>> materialByTypeAndGroup(PrdInfoVO prdInfo) {
		List<PrdInfoVO> list = prdInfoService.materialByTypeAndGroup(prdInfo);
		return R.data(list);
	}

	@GetMapping("/exportPrdInfo")
	//@ApiOperationSupport(order = 10)
	@ApiOperation(value = "导出产品主数据", notes = "equipmentInfo，ids")
	public void exportPrdInfo(HttpServletRequest request, HttpServletResponse response, String ids, PrdInfoVO prdInfo) {
		prdInfoService.exportPrdInfo(request, response, prdInfo, ids);
	}

	@GetMapping("/exportWaste")
	//@ApiOperationSupport(order = 10)
	@ApiOperation(value = "导出废品返修金额设置", notes = "equipmentInfo，ids")
	public void exportWaste(HttpServletRequest request, HttpServletResponse response, String ids, PrdInfoVO prdInfo) {
		prdInfoService.exportWaste(request, response, prdInfo, ids);
	}


	@GetMapping("/findByMaterialNo")
	//@ApiOperationSupport(order = 11)
	@ApiOperation(value = "根据产品编码查询产品信息", notes = "materialNo")
	public R<PrdInfoVO> findByMaterialNo(@RequestParam String materialNo) {
		return R.data(prdInfoService.findByMaterialNo(materialNo));
	}

	@GetMapping("/findByProductionLine")
	//@ApiOperationSupport(order = 12)
	@ApiOperation(value = "根据产线查询产品信息", notes = "productionLine")
	public R<List<PrdInfo>> findByProductionLine(@RequestParam String productionLine) {
		LambdaQueryWrapper<PrdInfo> wrapper = new LambdaQueryWrapper();
		wrapper.like(PrdInfo::getProductionLineCode, productionLine);
		return R.data(prdInfoService.list(wrapper));
	}
}
